#include "EntityBoss.h"
#include "Visualisation.h"
#include "WorldModel.h"
#include "Rectangle.h"
#include "ExplosionManager.h"
#include "ProjectileManager.h"
#include "Sound.h"
#include "AI.h"


int CEntityBoss::indexBody=0;
int CEntityBoss::indexSide=0;
int CEntityBoss::indexEye=0;
int CEntityBoss::indexMouth=0;
int CEntityBoss::indexAnimEye=0;
int CEntityBoss::indexAnimMouth=0;

enum eStateBoss
{
	eStateBothAlive,
	eStateLeftDead,
	eStateBothDead
};
CEntityBoss::CEntityBoss(int timeToSpawn, int indexProjectileLeft, int indexProjectileRight):	 
			offsetXLeftSide(-15), offsetYLeftSide(82), offsetXRightSide(131),offsetYRightSide(39), 
			offsetXEye(43), offsetYEye(97),currentFrameAnimationEye(-1),timeLastFrameAnimationEye(-1), 
			offsetXMouth(76), offsetYMouth(87), entry(false),totalHealth(500), explodeLeft(false), 
			explodeRight(false),timeSpawnLastProjectileLeft(-1), timeBetweenProjectile(500),
			projectileTypeLeft(indexProjectileLeft),projectileTypeRight(indexProjectileRight),
			timeSpawnLastProjectileRight(-1),currentFrameAnimationMouth(-1),timeLastFrameAnimationMouth(-1),
			animationMouthOver(false),wayPointLeft(90,10), wayPointRight(400,10),timeLastWayPoint(-1)
											
{
	assert(indexProjectileLeft>0);
	assert(indexProjectileRight>0);

	this->timeToSpawn=timeToSpawn;
	this->currentPosX=60;
	this->currentPosY=-400;
	CRectangle collision(0,150,0,150);
	this->collisionRectangle=collision;
	this->side=eSideEnemy;
	this->collisionCost=200;
	this->currentHealth=totalHealth;
	this->state=eStateBothAlive;
	switch(AI.getDifficulty())
	{
		case eDifficultyEasy:
			speed=5000;
		break;

		case eDifficultyNormal:
			speed=4000;
		break;

		case eDifficultyHard:
			speed=3000;
		break;
	}
}
CEntityBoss::~CEntityBoss(void){}

void CEntityBoss::update(void)
{
	if((int)HAPI->GetTime()>=WMODEL.getTimeStartLevel()+timeToSpawn)
	{
		if(this->currentHealth<=0)
		{
			WMODEL.setNumberOfPoint(WMODEL.getNumberOfPoint()+1000);
			die();
		}
		//calcul new position
		calculPositionLERP();
		
		checkCollision();

		//if health >400, the boss shoot on the left side
		if(currentHealth>=400)
		{
			if(currentPosY>=0)
			{
				shootProjectileLeft();
			}
		}
		//if health >200, the boss shoot on the right side
		if(currentHealth>=200)
		{
			if(currentPosY>=0)
			{
				shootProjectileRight();
			}
		}
		//if health<200 the boss shoot with his mouth
		else
		{
			shootProjectileMiddle();
		}
		//change of the state
		if(currentHealth>=200 && currentHealth<400)
		{
			state=eStateLeftDead;
			//spawn of the explosion
			if(explodeLeft==false)
			{
				EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONSHIP), 
				currentPosX+offsetXLeftSide+10, currentPosY+offsetYLeftSide+45);
				explodeLeft=true;
				SOUND.stopSound(eSoundExplosionBoss);
				SOUND.playSound(eSoundExplosionBoss,eVolumeHigh);
			}
		}
		if(currentHealth<200)
		{
			state=eStateBothDead;
			//spawn of the explosion
			if(explodeRight==false)
			{
				EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONSHIP), 
				currentPosX+offsetXRightSide+15, currentPosY+offsetYRightSide+75);
				explodeRight=true;
				SOUND.stopSound(eSoundExplosionBoss);
				SOUND.playSound(eSoundExplosionBoss,eVolumeHigh);
			}
		}
	}
}

void CEntityBoss::render(void)
{
	VIS.displayFrame(indexBody,currentPosX,currentPosY,1,true);
	VIS.displayAnimation(indexAnimEye,currentPosX+offsetXEye, currentPosY+offsetYEye,&currentFrameAnimationEye,
			&timeLastFrameAnimationEye,true);
	switch(state)
	{
		case eStateBothAlive:
			VIS.displayFrame(indexSide,currentPosX+offsetXLeftSide,currentPosY+offsetYLeftSide,1,true);
			VIS.displayFrame(indexSide,currentPosX+offsetXRightSide,currentPosY+offsetYRightSide,3,true);
			VIS.displayFrame(indexMouth,currentPosX+offsetXMouth, currentPosY+offsetYMouth,1,true);
			break;

		case eStateLeftDead:
			VIS.displayFrame(indexSide,currentPosX+offsetXLeftSide,currentPosY+offsetYLeftSide,2,true);
			VIS.displayFrame(indexSide,currentPosX+offsetXRightSide,currentPosY+offsetYRightSide,3,true);
			VIS.displayFrame(indexMouth,currentPosX+offsetXMouth, currentPosY+offsetYMouth,1,true);
			break;

		case eStateBothDead:
			VIS.displayFrame(indexSide,currentPosX+offsetXLeftSide,currentPosY+offsetYLeftSide,2,true);
			VIS.displayFrame(indexSide,currentPosX+offsetXRightSide,currentPosY+offsetYRightSide,4,true);
			if(animationMouthOver==false)
			{
				animationMouthOver=VIS.displayAnimation(indexAnimMouth,currentPosX+offsetXMouth, currentPosY+offsetYMouth,
				&currentFrameAnimationMouth,&timeLastFrameAnimationMouth,true);
			}
			else
			{
				VIS.displayFrame(indexMouth,currentPosX+offsetXMouth, currentPosY+offsetYMouth,4,true);
			}
			break;
	}	
}

void CEntityBoss::initialiseBoss(int indexBody, int indexSide, int indexEye, int indexMouth, 
		int indexAnimEye, int indexAnimMouth)
{
	assert(indexBody>=0);
	assert(indexSide>=0);
	assert(indexEye>=0);
	assert(indexMouth>=0);
	assert(indexAnimEye>=0);
	assert(indexAnimMouth>=0);

	CEntityBoss::indexBody=indexBody;
	CEntityBoss::indexSide=indexSide;
	CEntityBoss::indexEye=indexEye;
	CEntityBoss::indexMouth=indexMouth;
	CEntityBoss::indexAnimEye=indexAnimEye;
	CEntityBoss::indexAnimMouth=indexAnimMouth;

}
void CEntityBoss::resetBoss(void)
{
	this->currentHealth=this->totalHealth;
	this->timeSpawnLastProjectileLeft=-1;
	this->timeSpawnLastProjectileRight=-1;
	this->currentFrameAnimationEye=-1;
	this->animationMouthOver=false;
	this->currentPosX=90;
	this->currentPosY=-400;
	this->entry=false;
	this->explodeLeft=false;
	this->explodeRight=false;
	this->active=true;
	this->timeLastWayPoint=-1;
	this->state=eStateBothAlive;

	switch(AI.getDifficulty())
	{
		case eDifficultyEasy:
			speed=5000;
		break;

		case eDifficultyNormal:
			speed=4000;
		break;

		case eDifficultyHard:
			speed=3000;
		break;
	}
}

void CEntityBoss::shootProjectileLeft(void)
{
	if(this->timeSpawnLastProjectileLeft==-1)
	{
		this->timeSpawnLastProjectileLeft=HAPI->GetTime();
	}
	if(this->timeSpawnLastProjectileLeft+this->timeBetweenProjectile<(int)HAPI->GetTime())
	{
		PROJECTILEMANAGER.spawnProjectile(PROJECTILEMANAGER.getProjectileTemplate(projectileTypeLeft),
			this->currentPosX-10,this->currentPosY+130);
		this->timeSpawnLastProjectileLeft=HAPI->GetTime();
		SOUND.stopSound(eSoundEnemyShoot);
		SOUND.playSound(eSoundEnemyShoot,eVolumeLow);
	}
}
void CEntityBoss::shootProjectileRight(void)
{
	if(this->timeSpawnLastProjectileRight==-1)
	{
		this->timeSpawnLastProjectileRight=HAPI->GetTime();
	}
	if(this->timeSpawnLastProjectileRight+this->timeBetweenProjectile<(int)HAPI->GetTime())
	{
		PROJECTILEMANAGER.spawnProjectile(PROJECTILEMANAGER.getProjectileTemplate(projectileTypeRight),
			this->currentPosX+140,this->currentPosY+130);
		this->timeSpawnLastProjectileRight=HAPI->GetTime();
		SOUND.stopSound(eSoundEnemyShoot);
		SOUND.playSound(eSoundEnemyShoot,eVolumeLow);
	}
}
void CEntityBoss::shootProjectileMiddle(void)
{
	if(this->timeSpawnLastProjectileLeft==-1)
	{
		this->timeSpawnLastProjectileLeft=HAPI->GetTime();
	}
	if(this->timeSpawnLastProjectileLeft+this->timeBetweenProjectile<(int)HAPI->GetTime())
	{
		PROJECTILEMANAGER.spawnProjectile(PROJECTILEMANAGER.getProjectileTemplate(projectileTypeLeft),
			this->currentPosX+90,this->currentPosY+50);
		this->timeSpawnLastProjectileLeft=HAPI->GetTime();
		SOUND.stopSound(eSoundEnemyShoot);
		SOUND.playSound(eSoundEnemyShoot,eVolumeLow);
	}
}

void CEntityBoss::checkCollision(void)
{
	CWorldEntity* collision=WMODEL.checkCollision(this);
	if(collision!=NULL)
	{
		this->currentHealth-=collision->getCollisionCost();
		collision->setCurrentHealth(collision->getCurrentHealth()-this->collisionCost);
		if(this->currentHealth<=0)
		{
			WMODEL.setNumberOfPoint(WMODEL.getNumberOfPoint()+1000);
			die();
		}
	}
}
void CEntityBoss::calculPositionLERP(void)
{
	if(entry==false)
	{
		currentPosY+=3;
		if(currentPosY>=10)
		{
			currentPosY=10;
			entry=true;
		}
	}
	else
	{
		if(timeLastWayPoint==-1)
		{
			timeLastWayPoint=(float)HAPI->GetTime();
			nextWayPoint=wayPointRight;
			previousWayPoint=wayPointLeft;
		}
		float s=((float)HAPI->GetTime()-timeLastWayPoint)/(float)speed;
		currentPosX=(int)(previousWayPoint.getX()+s*(nextWayPoint.getX()-previousWayPoint.getX()));
		currentPosY=(int)(previousWayPoint.getY()+s*(nextWayPoint.getY()-previousWayPoint.getY()));
		if(s>1 || (currentPosX==nextWayPoint.getX() && currentPosY==nextWayPoint.getY()))
		{
			timeLastWayPoint=(float)HAPI->GetTime();
			CVector2D temp=nextWayPoint;
			nextWayPoint=previousWayPoint;
			previousWayPoint=temp;
		}
	}
}
void CEntityBoss::die(void)
{
	EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONSHIP),
		currentPosX,currentPosY);
	EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONSHIP),
		currentPosX+20,currentPosY);
	EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONSHIP),
		currentPosX+20,currentPosY+30);
	EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONSHIP),
		currentPosX+40,currentPosY+40);
	EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONSHIP),
		currentPosX+20,currentPosY+40);
	EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONSHIP),
		currentPosX+40,currentPosY+50);
	EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONSHIP),
		currentPosX+40,currentPosY);
	EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONSHIP),
		currentPosX+50,currentPosY+50);
	EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONSHIP),
		currentPosX+50,currentPosY+60);
	EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONSHIP),
		currentPosX+50,currentPosY+15);
	EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONSHIP),
		currentPosX+60,currentPosY+20);
	EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONSHIP),
		currentPosX+60,currentPosY+40);
	EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONSHIP),
		currentPosX+60,currentPosY+70);
	EXPLOSIONMANAGER.spawnExplosion(EXPLOSIONMANAGER.getExplosionTemplate(eEXPLOSIONSHIP),
		currentPosX+60,currentPosY+40);
	this->active=false;
	SOUND.stopSound(eSoundExplosion);
	SOUND.stopSound(eSoundExplosionBoss);
	SOUND.playSound(eSoundExplosionBoss,eVolumeMedium);
	SOUND.playSound(eSoundExplosion,eVolumeMedium);
}

